﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenExpressApp.Template;
using OpenExpressApp.WPF.Controls;
using System.ComponentModel;
using System.Windows.Controls;
using System.Windows;
using Csla.Core;
using OpenExpressApp.MetaModel;
using OpenExpressApp.WPF.Command;
using System.Reflection;
using AvalonDock;
using Itenso.Windows.Input;
using Csla.Wpf;
using System.Windows.Data;
using OpenExpressApp.Types;
using OpenExpressApp.MetaAttribute;

namespace OpenExpressApp.Module.WPF.Templete
{
    /// <summary>
    /// 这个ViewDataLoader其实是类似于装饰模式的一种实现。
    /// 
    /// 它把所有的数据请求都代理到了内部使用的ViewDataLoader上。
    /// </summary>
    public class QueryFormController : BaseListFrameController, IQueryFormViewController
    {
        private BaseQueryObject _queryObject;

        private TabControl _tabControl;

        private Dictionary<Type, IViewDataLoader> _viewControllers = new Dictionary<Type, IViewDataLoader>();

        private object[] _getListParam;

        public QueryFormController(IWindowTemplate windowTemplate, params object[] getListParam)
            : base(windowTemplate)
        {
            this._getListParam = getListParam;
            this._tabControl = this.FrameTemplate.GetRegion(ViewRegionNames.ListRegion) as TabControl;
            this._queryObject = Activator.CreateInstance(EntityType) as BaseQueryObject;
            windowTemplate.View.DataLoader = this;

            this.GenerateQueryPanel();

            //每个QueryObject生成一个TabItem
            foreach (var item in this._queryObject.QueryObjects)
            {
                this.CreateTabItem(item);
            }

            this._tabControl.SelectionChanged += new SelectionChangedEventHandler(tabControl_SelectionChanged);
            if (this._tabControl.Items.Count > 0)
            {
                this._tabControl.SelectedIndex = 0;
            }

            ExecAutoCommands(this.EntityType, this.View);

            //主工具条
            ToolBar mainToolBar = windowTemplate.GetRegion(ViewRegionNames.MainToolBar) as ToolBar;
            mainToolBar.DataContext = View;
            AutoUI.UIFactory.CreateMainToolBar(mainToolBar, EntityType, View, windowTemplate.ModuleType);
        }

        private Type EntityType
        {
            get
            {
                return this.FrameTemplate.View.BOType;
            }
        }

        /// <summary>
        /// 根据queryObjInfo生成一个TabItem放入TabControl中。
        /// </summary>
        /// <param name="queryObjInfo"></param>
        private void CreateTabItem(QueryObjectAttribute queryObjInfo)
        {
            Type type = queryObjInfo.ObjectType;

            //生成View和Controller
            WPFObjectView view = null;
            if (ViewType.DetailView == queryObjInfo.ViewType)
            {
                //生成DetailView
                var detailView = new DetailObjectView(type);
                detailView.DataLoader = new DetailViewController(detailView);
                view = detailView;
            }
            else
            {
                //根据对象类型自动生成View
                view = DefaultViewCreator.Create(type);
                if (view == null)
                {
                    //生成ListView
                    var listView = new ListObjectView(type);
                    //QueryForm下的所有查询对象都公用同一个NavigateQueryType
                    listView.NavigateQueryView = this.View.NavigateQueryView;
                    listView.DataLoader =new ListViewController(listView);
                    view = listView;
                }
            }
            this._viewControllers.Add(type, view.DataLoader);

            view.Parent = this.View;

            var typeInfo = ApplicationModel.GetBusinessObjectInfo(type);

            //开始生成控件
            TabItem ti = new TabItem();
            ti.Header = typeInfo.Label;
            ti.SetValue(WPFMeta.ObjectViewProperty, view);

            DockPanel dck = new DockPanel();

            //生成查询对象主工具条
            var toolBarTray = new ToolBarTray();
            toolBarTray.SetValue(DockPanel.DockProperty, Dock.Top);

            var toolBar = new ToolBar();
            FrameworkElement viewControllerControl = (view.DataLoader as IControlWrapper).Control as FrameworkElement;
            toolBar.SetServicedControl(viewControllerControl);
            AutoUI.UIFactory.CreateMainToolBar(toolBar, type, view, typeInfo.BusinessObjectAttribute.ModuleType);

            toolBarTray.ToolBars.Add(toolBar);
            dck.Children.Add(toolBarTray);
            dck.Children.Add(viewControllerControl);

            ti.Content = dck;

            ViewAdapter.AdaptView(view, ti);

            this._tabControl.Items.Add(ti);
        }

        /// <summary>
        /// 生成查询面板的控件
        /// </summary>
        private void GenerateQueryPanel()
        {
            //生成条件查询面板
            var conditionView = this.View.CondtionQueryView;
            if (conditionView != null)
            {
                Panel conditionQueryRegion = this.FrameTemplate.GetRegion(ViewRegionNames.ConditionQueryRegion) as Panel;

                var toolBarTray = new ToolBarTray();
                toolBarTray.SetValue(DockPanel.DockProperty, Dock.Top);

                var toolBar = new ToolBar();

                Button btnQuery = new Button();
                btnQuery.CommandParameter = conditionView;
                ButtonCommand.SetCommand(btnQuery, CommandRepository.NewCommand(CommandNames.QueryObject));

                Button btnClearCondition = new Button();
                btnClearCondition.CommandParameter = conditionView;
                ButtonCommand.SetCommand(btnClearCondition, CommandRepository.NewCommand(CommandNames.ClearQueryCondition));

                toolBar.Items.Add(btnQuery);
                toolBar.Items.Add(btnClearCondition);
                toolBarTray.ToolBars.Add(toolBar);
                conditionQueryRegion.Children.Add(toolBarTray);
                conditionQueryRegion.Children.Add(conditionView.Control);

                //初始化对象
                conditionView.Data = Activator.CreateInstance(conditionView.BOType);
               // (conditionView.CurrentObject as BusinessBase).BeginEdit();
            }

            //生成导航查询面板
            var naviView = this.View.NavigateQueryView;
            if (naviView != null)
            {
                Panel navigateQueryRegion = this.FrameTemplate.GetRegion(ViewRegionNames.NavigateQueryRegion) as Panel;
                navigateQueryRegion.Children.Add(naviView.Control);

                //初始化对象
                naviView.Data = Activator.CreateInstance(naviView.BOType);
               // (naviView.CurrentObject as BusinessBase).BeginEdit();
            }
        }

        /// <summary>
        /// 是否需要自动加载这个类型的数据。
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private bool AutoLoadList(Type type)
        {
            var item = this._queryObject.QueryObjects.FirstOrDefault(q => q.ObjectType == type);
            if (item != null)
            {
                return item.AutoLoadList;
            }
            return false;
        }

        /// <summary>
        /// 页签变换时，加载数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (sender == e.OriginalSource &&
                e.AddedItems.Count > 0 &&
                e.AddedItems[0] is TabItem
                )
            {
                foreach (TabItem item in e.AddedItems)
                {
                    var view = item.GetValue(WPFMeta.ObjectViewProperty) as ObjectView;
                    view.IsActive = true;

                    var controller = this._viewControllers[view.BOType];
                    if (view.Data == null && this._lastCriteria != null)
                    {
                        controller.AsyncGetObject(this._lastCriteria);
                    }
                    //AutoLoadData
                    else if (this.AutoLoadList(view.BOType))
                    {
                        controller.AsyncGetObject(this._getListParam);
                    }
                }

                foreach (TabItem item in e.RemovedItems)
                {
                    var view = item.GetValue(WPFMeta.ObjectViewProperty) as ObjectView;
                    view.IsActive = false;
                }

                e.Handled = true;
            }
        }

        #region IQueryFormViewController 成员

        /// <summary>
        /// 最后一次使用的Criteria
        /// </summary>
        private IQueryObject _lastCriteria;

        ObjectView IViewDataLoader.View
        {
            get
            {
                return this.View;
            }
        }

        public void AsyncGetObject(params object[] getListParam)
        {
            var target = this.FindActiveController();
            if (target != null)
            {
                this.PrepareEvent(target);
                target.AsyncGetObject(getListParam);
            }
        }

        public void AsyncGetObject(string getListMethod, params object[] getListParam)
        {
            var target = this.FindActiveController();
            if (target != null)
            {
                this.PrepareEvent(target);
                target.AsyncGetObject(getListMethod, getListParam);
            }
        }

        public void AsyncGetObject(IQueryObject criteria)
        {
            this._lastCriteria = criteria;
            (this as IViewDataLoader).AsyncGetObject(new object[] { criteria });
        }

        public void AsyncGetObject(string getListMethod, IQueryObject criteria)
        {
            this._lastCriteria = criteria;
            (this as IViewDataLoader).AsyncGetObject(getListMethod, new object[] { criteria });
        }

        public IViewDataLoader GetViewController(Type type)
        {
            return this._viewControllers[type];
        }

        public bool IsLoadingData
        {
            get
            {
                return this._lastLoader != null && this._lastLoader.IsLoadingData;
            }
        }

        public void CancelLoading()
        {
            if (this._lastLoader != null)
            {
                this._lastLoader.CancelLoading();
            }
        }

        /// <summary>
        /// 正在使用的加载器
        /// </summary>
        private IViewDataLoader _lastLoader;

        public event EventHandler<DataLoadedEventArgs> DataLoaded;

        public event EventHandler DataChanged;

        private void PrepareEvent(IViewDataLoader loader)
        {
            this._lastLoader = loader;

            loader.ListenDataLoadedOnce(e =>
            {
                if (this.DataLoaded != null)
                {
                    this.DataLoaded(this, e);
                }
            });

            loader.ListenDataChangedOnce(() =>
            {
                if (this.DataChanged != null)
                {
                    this.DataChanged(this, EventArgs.Empty);
                }
            });
        }

        #endregion

        /// <summary>
        /// 查询处于激活状态的页签
        /// </summary>
        /// <param name="criteria"></param>
        private IViewDataLoader FindActiveController()
        {
            return this.FindActiveController(false);
        }

        /// <summary>
        /// 查询处于激活状态的页签
        /// </summary>
        /// <param name="checkAutoLoad">
        /// 是否对激活状态的页签检查是否标记了AutoLoad。
        /// </param>
        /// <returns></returns>
        private IViewDataLoader FindActiveController(bool checkAutoLoad)
        {
            IViewDataLoader target = null;

            foreach (var entry in this._viewControllers)
            {
                entry.Value.View.Data = null;
                if (entry.Value.View.IsActive)
                {
                    if (checkAutoLoad && AutoLoadList(entry.Key) == false) continue;

                    target = entry.Value;
                }
            }

            return target;
        }
    }
}
